#include "ThreadPool.h" 
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//#include <sys/prctl.h>
#ifdef __linux__
#include <pthread.h>
#elif defined(_WIN32)
#include <windows.h>
#endif

namespace zl
{
	ThreadPool::ThreadPool(int threadNum)
	{
		isRunning_ = true;
		threadsNum_ = threadNum;
		createThreads();
	}

	ThreadPool::~ThreadPool()
	{
		stop();
		for (auto task : taskQueue_)
		{
			delete task;
		}
		taskQueue_.clear();
	}

	void ThreadPool::createThreads()
	{
		for (int i = 0; i < threadsNum_; ++i)
		{
			threads_.emplace_back([this] { threadFunc(); });
		}
	}

	size_t ThreadPool::addTask(Task* task)
	{
		std::lock_guard<std::mutex> lock(mutex_);
		taskQueue_.push_back(task);
		condition_.notify_one();
		return taskQueue_.size();
	}

	void ThreadPool::stop()
	{
		if (!isRunning_)
			return;

		{
			std::unique_lock<std::mutex> lock(mutex_);
			isRunning_ = false;
			condition_.notify_all();
		}

		for (auto& thread : threads_)
		{
			if (thread.joinable())
				thread.join();
		}
	}

	int ThreadPool::size()
	{
		std::lock_guard<std::mutex> lock(mutex_);
		return taskQueue_.size();
	}

	Task* ThreadPool::take()
	{
		std::unique_lock<std::mutex> lock(mutex_);
		condition_.wait(lock, [this] { return !taskQueue_.empty() || !isRunning_; });

		if (!isRunning_)
			return nullptr;

		Task* task = taskQueue_.front();
		taskQueue_.pop_front();
		return task;
	}

	void ThreadPool::threadFunc()
	{
#ifdef __linux__
		pthread_setname_np(pthread_self(), "ThreadPoolThread");
#elif defined(_WIN32)
		SetThreadDescription(GetCurrentThread(), L"ThreadPoolThread");
#endif

		while (isRunning_)
		{
			Task* task = take();
			if (task)
			{
				task->run();
				delete task;
			}
		}
	}
}
